/*
 * Copyright © 2011 Nokia Corporation. All rights reserved.
 * Nokia and Nokia Connecting People are registered trademarks of Nokia Corporation. 
 * Oracle and Java are trademarks or registered trademarks of Oracle and/or its
 * affiliates. Other product and company names mentioned herein may be trademarks
 * or trade names of their respective owners. 
 * See LICENSE.TXT for license information.
 */ 

package com.nokia.example.wordpress.networking;

import java.io.*;
import javax.microedition.io.*;

/**
 * Provides asynchronous HTTP GET and POST operations.
 */
public class Network implements Runnable {

    private NetworkListener listener;
    private String url = null;
    private String request = null;

    /**
     * Constructor
     * @param listener
     */
    public Network(NetworkListener listener) {
        this.listener = listener;
    }

    /**
     * Sends a GET request synchronously.
     * @param url Target of the request.
     * @return Data received
     * @throws NetworkError
     */
    private byte[] sendHttpGet(String url) throws NetworkError {
        HttpConnection hcon = null;
        DataInputStream dis = null;
        ByteArrayOutputStream response = new ByteArrayOutputStream();

        try {
            // a standard HttpConnection with READ access
            hcon = (HttpConnection) Connector.open(url);

            if (hcon == null) {
                throw new NetworkError("No network access");
            }

            // obtain a DataInputStream from the HttpConnection
            dis = new DataInputStream(hcon.openInputStream());

            // retrieve the response from the server
            int ch;
            while ((ch = dis.read()) != -1) {
                response.write((byte) ch);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new NetworkError(e.getMessage());
        } finally {
            try {
                if (hcon != null) {
                    hcon.close();
                }
                if (dis != null) {
                    dis.close();
                }
            } catch (IOException ioe) {
                ioe.printStackTrace();
            }
        }
        return response.toByteArray();
    }

    /**
     * Sends a POST request synchronously.
     * @param url Target for the request.
     * @param request Request body
     * @throws NetworkError
     */
    private String sendHttpPost(String url, String request) throws NetworkError {
        HttpConnection hcon = null;
        DataInputStream dis = null;
        DataOutputStream dos = null;
        StringBuffer responseMessage = new StringBuffer();

        try {
            // an HttpConnection with both read and write access
            hcon = (HttpConnection) Connector.open(url, Connector.READ_WRITE);
            if (hcon == null) {
                throw new NetworkError("No network access");
            }

            // set the request method to POST
            hcon.setRequestMethod(HttpConnection.POST);

            // obtain DataOutputStream for sending the request string
            dos = hcon.openDataOutputStream();
            byte[] request_body = request.getBytes();

            // send request string to server
            for (int i = 0; i < request_body.length; i++) {
                dos.writeByte(request_body[i]);
            }

            // obtain DataInputStream for receiving server response
            dis = new DataInputStream(hcon.openInputStream());

            // retrieve the response from server
            int ch;
            while ((ch = dis.read()) != -1) {
                responseMessage.append((char) ch);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new NetworkError(e.getMessage());
        } finally {
            // free up i/o streams and http connection
            try {
                if (hcon != null) {
                    hcon.close();
                }
                if (dis != null) {
                    dis.close();
                }
                if (dos != null) {
                    dos.close();
                }
            } catch (IOException ioe) {
                ioe.printStackTrace();
            }
        }
        return responseMessage.toString();
    }

    /**
     * Thread entry point. Network operation is run in a separate thread.
     */
    public void run() {
        try {
            if (request == null) {
                byte[] data = sendHttpGet(url);
                listener.networkHttpGetResponse(data);
            } else {
                String response = sendHttpPost(url, request);
                listener.networkHttpPostResponse(response);
            }
        } catch (NetworkError e) {
            if (request == null) {
                listener.networkHttpGetResponse(null);
            } else {
                listener.networkHttpPostResponse(null);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Sends a HTTP POST request asynchronously, returns immediately and
     * reports later using the listener.
     * @param url Target url
     * @param request Body
     */
    void startHttpPost(String url, String request) {
        this.url = url;
        this.request = request;
        Thread thread = new Thread(this);
        thread.start();
    }

    /**
     * Sends a HTTP GET request asynchronously, returns immediately and
     * reports later using the listener.
     * @param url Target url
     */
    public void startHttpGet(String url) {
        this.url = url;
        Thread thread = new Thread(this);
        thread.start();
    }
}


